#include "Animation.h"

Animation::Animation()
{
    timer.SetOneShot(false);
    timer.SetOnTimeout([&]() {
                idxFrame++;
                if (idxFrame >= rectSrcList.size()) {
                    idxFrame = isLoop ? 0 : rectSrcList.size() - 1;
                    if (!isLoop && onFinished)
                        onFinished();
                }
            }
    );
}

void Animation::Reset()
{
    timer.Restart();
    idxFrame = 0;
}

void Animation::SetFrameData(SDL_Texture *srcTexture, int num_h, int num_v, const std::vector<int> &idx_list)
{
    int widthTex, heightTex;

    this->texture = srcTexture;
    SDL_QueryTexture(srcTexture, nullptr, nullptr, &widthTex, &heightTex);
    widthFrame = widthTex / num_h, heightFrame = heightTex / num_v;

    rectSrcList.resize(idx_list.size());
    for (size_t i = 0; i < idx_list.size(); i++) {
        int idx = idx_list[i];
        SDL_Rect &rect_src = rectSrcList[i];

        rect_src.x = (idx % num_h) * widthFrame;
        rect_src.y = (idx / num_h) * heightFrame;
        rect_src.w = widthFrame, rect_src.h = heightFrame;
    }
}

void Animation::SetLoop(bool flag)
{
    this->isLoop = flag;
}

void Animation::SetInterval(double interval)
{
    timer.SetWaitTime(interval);
}

void Animation::SetOnFinished(PlayCallback playCallback)
{
    this->onFinished = std::move(playCallback);
}

void Animation::OnUpdate(double delta)
{
    timer.OnUpdate(delta);
}

void Animation::OnRender(SDL_Renderer *renderer, const SDL_Point &pos_dst, double angle) const
{
    static SDL_Rect rect_dst;
    rect_dst.x = pos_dst.x, rect_dst.y = pos_dst.y;
    rect_dst.w = widthFrame, rect_dst.h = heightFrame;
    SDL_RenderCopyEx(renderer, texture, &rectSrcList[idxFrame], &rect_dst,
                     angle, nullptr, SDL_RendererFlip::SDL_FLIP_NONE);
}